/*
	This file is part of Warzone 2100.
	Copyright (C) 1999-2004  Eidos Interactive
	Copyright (C) 2005-2007  Warzone Resurrection Project

	Warzone 2100 is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	Warzone 2100 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Warzone 2100; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
 * @file component.c
 * Draws component objects - oh yes indeed.
*/
#include <string.h>

#include "lib/framework/frame.h"
#include "basedef.h"
#include "droid.h"
#include "action.h"
#include "order.h"
#include "component.h"
#include "lib/ivis_common/ivisdef.h" //ivis matrix code
#include "lib/ivis_opengl/piematrix.h"
#include "lib/ivis_common/piedef.h" //ivis matrix code
#include "lib/ivis_common/piestate.h" //ivis render code
#include "lib/ivis_common/piepalette.h"
#include "lighting.h"
#include "loop.h"

#define GetRadius(x) ((x)->sradius)

#include "stats.h"
#include "lib/ivis_common/piemode.h"
#include "objects.h"
#include "display.h"
#include "geometry.h"
#include "display3d.h"
#include "map.h"
#include "lib/gamelib/gtime.h"
#include "intdisplay.h"
#include "miscimd.h"
#include "effects.h"
#include "e3demo.h"
#include "transporter.h"
#include "projectile.h"

static void unsetMatrix(void);
static void setMatrix(Vector3i *Position, Vector3i *Rotation, BOOL RotXYZ);

#define BLIP_ANIM_DURATION			200
#define	DEFAULT_COMPONENT_TRANSLUCENCY	128
#define	DROID_EMP_SPREAD	(20 - rand()%40)

//Watermelon:VTOL weapon connector start
#define VTOL_CONNECTOR_START 5

static void displayCompObj(BASE_OBJECT *psObj, BOOL bButton);
static iIMDShape *getLeftPropulsionIMD(DROID *psDroid);
static iIMDShape *getRightPropulsionIMD(DROID *psDroid);
static UDWORD getStructureHeight(STRUCTURE *psStructure);

static BOOL		leftFirst;
static SDWORD		droidLightLevel = 224;
static UDWORD		lightInterval = 15;
static UDWORD		lightLastChanged;
SDWORD		lightSpeed=2;
extern UDWORD selectedPlayer;

UBYTE		PlayerColour[MAX_PLAYERS];// = {0,1,2,3,4,5,6,7}

// Colour Lookups
// use col = MAX_PLAYERS for anycolour (see multiint.c)
BOOL setPlayerColour(UDWORD player, UDWORD col)
{
	if(player >MAX_PLAYERS || col >MAX_PLAYERS)
	{
		debug( LOG_ERROR, "setplayercolour: wrong values" );
		abort();
		return false;
	}
	PlayerColour[(UBYTE)player] = (UBYTE)col;
	return true;
}

UBYTE getPlayerColour(UDWORD pl)
{
	return PlayerColour[pl];
}

void initPlayerColours(void)
{
	UBYTE i;
	for(i=0;i<MAX_PLAYERS;i++)
	{
		PlayerColour[i] = i;
	}
}


void updateLightLevels(void)
{
	if(gameTime>(lightLastChanged+lightInterval))
	{
	   	droidLightLevel+=lightSpeed;
		lightLastChanged = gameTime;
	 	if(droidLightLevel>255 || droidLightLevel<128)
		{
			if(lightSpeed>0)
			{
					lightSpeed = -lightSpeed;
			}
			else
			{
					lightSpeed = -lightSpeed;
			}
		}
	}
}


static void setMatrix(Vector3i *Position, Vector3i *Rotation, BOOL RotXYZ)
{
	pie_PerspectiveBegin();
   	pie_MatBegin();

	pie_TRANSLATE(Position->x,Position->y,Position->z);

	if(RotXYZ) {
		pie_MatRotX(DEG(Rotation->x));
		pie_MatRotY(DEG(Rotation->y));
		pie_MatRotZ(DEG(Rotation->z));
	} else {
		pie_MatRotY(DEG(Rotation->y));
		pie_MatRotX(DEG(Rotation->x));
		pie_MatRotZ(DEG(Rotation->z));
	}
}


static void unsetMatrix(void)
{
	pie_MatEnd();
	pie_PerspectiveEnd();
}


UDWORD getComponentDroidRadius(WZ_DECL_UNUSED DROID *psDroid)
{
	return 100;
}


UDWORD getComponentDroidTemplateRadius(WZ_DECL_UNUSED DROID_TEMPLATE *psDroid)
{
	return 100;
}


UDWORD getComponentRadius(BASE_STATS *psComponent)
{
	iIMDShape *ComponentIMD = NULL;
	iIMDShape *MountIMD = NULL;
	SDWORD compID;

	compID = StatIsComponent(psComponent);
	if (compID > 0)
	{
		StatGetComponentIMD(psComponent, compID,&ComponentIMD, &MountIMD);
		if(ComponentIMD)
		{
			return GetRadius(ComponentIMD);
		}
	}

	/* VTOL bombs are only stats allowed to have NULL ComponentIMD */
	if (StatIsComponent(psComponent) != COMP_WEAPON
	    || (((WEAPON_STATS *)psComponent)->weaponSubClass != WSC_BOMB
	        && ((WEAPON_STATS *)psComponent)->weaponSubClass != WSC_EMP))
	{
		ASSERT(ComponentIMD, "No ComponentIMD!");
	}

	return COMPONENT_RADIUS;
}


UDWORD getResearchRadius(BASE_STATS *Stat)
{
	iIMDShape *ResearchIMD = ((RESEARCH *)Stat)->pIMD;

	if(ResearchIMD) {
		return GetRadius(ResearchIMD);
	}

	debug(LOG_ERROR, "getResearchRadius: ResearchPIE == NULL");

	return 100;
}


UDWORD getStructureSize(STRUCTURE *psStructure)
{
	UDWORD size;
	//radius based on base plate size

	size = psStructure->pStructureType->baseWidth;
	if (psStructure->pStructureType->baseBreadth > size)
	{
		size = psStructure->pStructureType->baseBreadth;
	}
	return (size);
}

UDWORD getStructureStatSize(STRUCTURE_STATS *Stats)
{
	UDWORD size;
	//radius based on base plate size

	size = Stats->baseWidth;
	if (Stats->baseBreadth > size)
	{
		size = Stats->baseBreadth;
	}
	return (size);
}

UDWORD getStructureHeight(STRUCTURE *psStructure)
{
	return (getStructureStatHeight(psStructure->pStructureType));
}

UDWORD getStructureStatHeight(STRUCTURE_STATS *psStat)
{
	if (psStat->pIMD)
	{
		return (psStat->pIMD->max.y - psStat->pIMD->min.y);
	}

	return 0;
}


void displayIMDButton(iIMDShape *IMDShape, Vector3i *Rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
{
	setMatrix(Position, Rotation, RotXYZ);
	pie_MatScale(scale);

	pie_SetFogStatus(false);
	pie_Draw3DShape(IMDShape, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
	unsetMatrix();
}


//Watermelon:changed it to loop thru and draw all weapons
void displayStructureButton(STRUCTURE *psStructure, Vector3i *Rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
{
	iIMDShape *baseImd,*strImd;//*mountImd,*weaponImd;
	iIMDShape *mountImd[STRUCT_MAXWEAPS];
	iIMDShape *weaponImd[STRUCT_MAXWEAPS];
	UDWORD			nWeaponStat;
	int		i;

	/*HACK HACK HACK!
	if its a 'tall thin (ie tower)' structure with something on the top - offset the
	position to show the object on top*/
	if (psStructure->pStructureType->pIMD->nconnectors && scale == SMALL_STRUCT_SCALE &&
	    getStructureHeight(psStructure) > TOWER_HEIGHT)
	{
		Position->y -= 20;
	}

	setMatrix(Position, Rotation, RotXYZ);
	pie_MatScale(scale);

	/* Draw the building's base first */
	baseImd = psStructure->pStructureType->pBaseIMD;
	if(baseImd!=NULL) {
		pie_Draw3DShape(baseImd, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
	}
	pie_Draw3DShape(psStructure->sDisplay.imd, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
	//and draw the turret
	if(psStructure->sDisplay.imd->nconnectors)
	{
		for (i = 0;i < STRUCT_MAXWEAPS;i++)
		{
			weaponImd[i] = NULL;//weapon is gun ecm or sensor
			mountImd[i] = NULL;
		}

		strImd = psStructure->sDisplay.imd;
		//get an imd to draw on the connector priority is weapon, ECM, sensor
		//check for weapon
		//Watermelon:re-enabled if (psStructure->numWeaps > 0)
		if (psStructure->numWeaps > 0)
		{
			for (i = 0;i < psStructure->numWeaps;i++)
			{
				if (psStructure->asWeaps[i].nStat > 0)
				{
					nWeaponStat = psStructure->asWeaps[i].nStat;
					weaponImd[i] =  asWeaponStats[nWeaponStat].pIMD;
					mountImd[i] =  asWeaponStats[nWeaponStat].pMountGraphic;
				}

				if (weaponImd[i] == NULL)
				{
					//check for ECM
					if (psStructure->pStructureType->pECM != NULL)
					{
						weaponImd[i] =  psStructure->pStructureType->pECM->pIMD;
						mountImd[i] =  psStructure->pStructureType->pECM->pMountGraphic;
					}
				}

				if (weaponImd[i] == NULL)
				{
					//check for sensor
					if (psStructure->pStructureType->pSensor != NULL)
					{
						weaponImd[i] =  psStructure->pStructureType->pSensor->pIMD;
						mountImd[i]  =  psStructure->pStructureType->pSensor->pMountGraphic;
					}
				}
			}
		}
		else
		{
			if (psStructure->asWeaps[0].nStat > 0)
			{
				nWeaponStat = psStructure->asWeaps[0].nStat;
				weaponImd[0] =  asWeaponStats[nWeaponStat].pIMD;
				mountImd[0] =  asWeaponStats[nWeaponStat].pMountGraphic;
			}

			if (weaponImd[0] == NULL)
			{
				//check for ECM
				if (psStructure->pStructureType->pECM != NULL)
				{
					weaponImd[0] =  psStructure->pStructureType->pECM->pIMD;
					mountImd[0] =  psStructure->pStructureType->pECM->pMountGraphic;
				}
			}

			if (weaponImd[0] == NULL)
			{
				//check for sensor
				if (psStructure->pStructureType->pSensor != NULL)
				{
					weaponImd[0] =  psStructure->pStructureType->pSensor->pIMD;
					mountImd[0]  =  psStructure->pStructureType->pSensor->pMountGraphic;
				}
			}

		}

		//draw Weapon/ECM/Sensor for structure
		//Watermelon:uses 0
		if(weaponImd[0] != NULL)
		{
			if (psStructure->numWeaps > 0)
			{
				for (i = 0;i < psStructure->numWeaps;i++)
				{
					iV_MatrixBegin();
					iV_TRANSLATE(strImd->connectors[i].x,strImd->connectors[i].z,strImd->connectors[i].y);
					pie_MatRotY(DEG(-((SDWORD)psStructure->turretRotation[i])));
					if (mountImd[i] != NULL)
					{
						pie_Draw3DShape(mountImd[i], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
						if(mountImd[i]->nconnectors)
						{
							iV_TRANSLATE(mountImd[i]->connectors->x,mountImd[i]->connectors->z,mountImd[i]->connectors->y);
						}
					}
					iV_MatrixRotateX(DEG(psStructure->turretPitch[i]));
					pie_Draw3DShape(weaponImd[i], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
					//we have a droid weapon so do we draw a muzzle flash
					iV_MatrixEnd();
				}
			}
			else
			{
				iV_MatrixBegin();
				iV_TRANSLATE(strImd->connectors->x,strImd->connectors->z,strImd->connectors->y);
				pie_MatRotY(DEG(-((SDWORD)psStructure->turretRotation[0])));
				if (mountImd[0] != NULL)
				{
					pie_Draw3DShape(mountImd[0], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
					if(mountImd[0]->nconnectors)
					{
						iV_TRANSLATE(mountImd[0]->connectors->x,mountImd[0]->connectors->z,mountImd[0]->connectors->y);
					}
				}
				iV_MatrixRotateX(DEG(psStructure->turretPitch[0]));
				pie_Draw3DShape(weaponImd[0], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
				//we have a droid weapon so do we draw a muzzle flash
				iV_MatrixEnd();
			}
		}
	}
	unsetMatrix();
}

void displayStructureStatButton(STRUCTURE_STATS *Stats, UDWORD Player, Vector3i *Rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
{
	iIMDShape		*baseImd,*strImd;//*mountImd,*weaponImd;
	iIMDShape *mountImd[STRUCT_MAXWEAPS];
	iIMDShape *weaponImd[STRUCT_MAXWEAPS];
	UBYTE	i;

	/*HACK HACK HACK!
	if its a 'tall thin (ie tower)' structure stat with something on the top - offset the
	position to show the object on top*/
	if (Stats->pIMD->nconnectors && scale == SMALL_STRUCT_SCALE &&
	    getStructureStatHeight(Stats) > TOWER_HEIGHT)
	{
		Position->y -= 20;
	}

	setMatrix(Position, Rotation, RotXYZ);
	pie_MatScale(scale);

	/* Draw the building's base first */
	baseImd = Stats->pBaseIMD;

	if (baseImd != NULL)
	{
		pie_Draw3DShape(baseImd, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
	}
	pie_Draw3DShape(Stats->pIMD, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);

	//and draw the turret
	if(Stats->pIMD->nconnectors)
	{
		if (Stats->numWeaps > 0)
		{
			for (i = 0;i < Stats->numWeaps;i++)
			{
				weaponImd[i] = NULL;//weapon is gun ecm or sensor
				mountImd[i] = NULL;
			}
		}
		else
		{
			weaponImd[0] = NULL;
			mountImd[0] = NULL;
		}
		strImd = Stats->pIMD;
		//get an imd to draw on the connector priority is weapon, ECM, sensor
		//check for weapon
		//Watermelon:can only have the STRUCT_MAXWEAPS
		if (Stats->numWeaps > 0)
		{
			for (i = 0;i < Stats->numWeaps;i++)
			{
				//can only have the one
				if (Stats->psWeapStat[i] != NULL)
				{
					weaponImd[i] = Stats->psWeapStat[i]->pIMD;
					mountImd[i] = Stats->psWeapStat[i]->pMountGraphic;
				}

				if (weaponImd[i] == NULL)
				{
					//check for ECM
					if (Stats->pECM != NULL)
					{
						weaponImd[i] =  Stats->pECM->pIMD;
						mountImd[i] =  Stats->pECM->pMountGraphic;
					}
				}

				if (weaponImd[i] == NULL)
				{
					//check for sensor
					if (Stats->pSensor != NULL)
					{
						weaponImd[i] =  Stats->pSensor->pIMD;
						mountImd[i]  =  Stats->pSensor->pMountGraphic;
					}
				}
			}
		}
		else
		{
			if (Stats->psWeapStat[0] != NULL)
			{
				weaponImd[0] = Stats->psWeapStat[0]->pIMD;
				mountImd[0] = Stats->psWeapStat[0]->pMountGraphic;
			}

			if (weaponImd[0] == NULL)
			{
				//check for ECM
				if (Stats->pECM != NULL)
				{
					weaponImd[0] =  Stats->pECM->pIMD;
					mountImd[0] =  Stats->pECM->pMountGraphic;
				}
			}

			if (weaponImd[0] == NULL)
			{
				//check for sensor
				if (Stats->pSensor != NULL)
				{
					weaponImd[0] =  Stats->pSensor->pIMD;
					mountImd[0]  =  Stats->pSensor->pMountGraphic;
				}
			}
		}

		//draw Weapon/ECM/Sensor for structure
		if(weaponImd[0] != NULL)
		{
			if (Stats->numWeaps > 0)
			{
				for (i = 0;i < Stats->numWeaps;i++)
				{
					iV_MatrixBegin();
					iV_TRANSLATE(strImd->connectors[i].x,strImd->connectors[i].z,strImd->connectors[i].y);
					pie_MatRotY(DEG(0));
					if (mountImd[i] != NULL)
					{
						pie_Draw3DShape(mountImd[i], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
						if(mountImd[i]->nconnectors)
						{
							iV_TRANSLATE(mountImd[i]->connectors->x,mountImd[i]->connectors->z,mountImd[i]->connectors->y);
						}
					}
					iV_MatrixRotateX(DEG(0));
					pie_Draw3DShape(weaponImd[i], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
					//we have a droid weapon so do we draw a muzzle flash
					iV_MatrixEnd();
				}
			}
			else
			{
				iV_MatrixBegin();
				iV_TRANSLATE(strImd->connectors[0].x,strImd->connectors[0].z,strImd->connectors[0].y);
				pie_MatRotY(DEG(0));
				if (mountImd[0] != NULL)
				{
					pie_Draw3DShape(mountImd[0], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
					if(mountImd[0]->nconnectors)
					{
						iV_TRANSLATE(mountImd[0]->connectors->x,mountImd[0]->connectors->z,mountImd[0]->connectors->y);
					}
				}
				iV_MatrixRotateX(DEG(0));
				pie_Draw3DShape(weaponImd[0], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
				//we have a droid weapon so do we draw a muzzle flash
				iV_MatrixEnd();
			}
		}
	}

	unsetMatrix();
}



// Render a component given a BASE_STATS structure.
//
void displayComponentButton(BASE_STATS *Stat, Vector3i *Rotation, Vector3i *Position,
                            BOOL RotXYZ, SDWORD scale)
{
	iIMDShape *ComponentIMD = NULL;
	iIMDShape *MountIMD = NULL;
	SDWORD compID;

	setMatrix(Position, Rotation, RotXYZ);
	pie_MatScale(scale);

	compID = StatIsComponent(Stat);
	if (compID > 0)	{
		StatGetComponentIMD(Stat, compID,&ComponentIMD, &MountIMD);
	}
	else
	{
		unsetMatrix();
		return;
	}

	/* VTOL bombs are only stats allowed to have NULL ComponentIMD */
	if (StatIsComponent(Stat) != COMP_WEAPON
	    || (((WEAPON_STATS *)Stat)->weaponSubClass != WSC_BOMB
	        && ((WEAPON_STATS *)Stat)->weaponSubClass != WSC_EMP))
	{
		ASSERT(ComponentIMD, "No ComponentIMD");
	}

	if(MountIMD)
	{
		pie_Draw3DShape(MountIMD, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
	}
	if(ComponentIMD)
	{
		pie_Draw3DShape(ComponentIMD, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
	}

	unsetMatrix();
}


// Render a research item given a BASE_STATS structure.
//
void displayResearchButton(BASE_STATS *Stat, Vector3i *Rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
{
	iIMDShape *ResearchIMD = ((RESEARCH *)Stat)->pIMD;
	iIMDShape *MountIMD = ((RESEARCH *)Stat)->pIMD2;

	if(ResearchIMD)
	{
		setMatrix(Position, Rotation, RotXYZ);
		pie_MatScale(scale);

		if(MountIMD) {
			pie_Draw3DShape(MountIMD, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
		}
		pie_Draw3DShape(ResearchIMD, 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);

		unsetMatrix();
	}
	else
	{
		debug(LOG_ERROR, "displayResearchButton: ResearchIMD == NULL");
	}
}



// Render a composite droid given a DROID_TEMPLATE structure.
//
void displayComponentButtonTemplate(DROID_TEMPLATE *psTemplate, Vector3i *Rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
{
	static DROID Droid;	// Made static to reduce stack usage.
	SDWORD difference;

	/* init to NULL */
	memset( &Droid, 0, sizeof(DROID) );

	setMatrix(Position, Rotation, RotXYZ);
	pie_MatScale(scale);

// Decide how to sort it.

	difference = Rotation->y%360;

	if((difference>0 && difference <180) || difference<-180)
	{
		leftFirst = false;
	}
	else
	{
		leftFirst = true;
	}

	droidSetBits(psTemplate,&Droid);
	Droid.player = (UBYTE)selectedPlayer;

	Droid.pos.x = Droid.pos.y = Droid.pos.z = 0;

	//draw multi component object as a button object
	displayCompObj((BASE_OBJECT*)&Droid, true);


	unsetMatrix();
}


// Render a composite droid given a DROID structure.
//
void displayComponentButtonObject(DROID *psDroid, Vector3i *Rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
{
	SDWORD		difference;

	setMatrix(Position, Rotation, RotXYZ);
	pie_MatScale(scale);

// Decide how to sort it.
	difference = Rotation->y%360;

	if((difference>0 && difference <180) || difference<-180)
	{
		leftFirst = false;
	}
	else
	{
		leftFirst = true;
	}

// And render the composite object.
	//draw multi component object as a button object
	displayCompObj((BASE_OBJECT*)psDroid, true);

	unsetMatrix();
}



/* Assumes matrix context is already set */
// Watermelon:multiple turrets display removed the pointless mountRotation
void displayComponentObject(BASE_OBJECT *psObj)
{
	DROID		*psDroid = (DROID *)psObj;
	Vector3i	position, rotation;
	Sint32		xShift,zShift;
	UDWORD		worldAngle;
	SDWORD		difference;
	SDWORD		frame;
	PROPULSION_STATS	*psPropStats;
	UDWORD	tileX,tileY;
	MAPTILE	*psTile;

	psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION].nStat;
	worldAngle = (UDWORD)(player.r.y / DEG_1) % 360;
	difference = worldAngle - psObj->direction;

	if((difference>0 && difference <180) || difference<-180)
	{
		leftFirst = false;
	}
	else
	{
		leftFirst = true;
	}

	/* Push the matrix */
	pie_MatBegin();

	/* Get internal tile units coordinates */
	xShift = map_round(player.p.x);
	zShift = map_round(player.p.z);

	/* Mask out to tile_units resolution */
	pie_TRANSLATE(xShift,0,-zShift);

	/* Get the real position */
	position.x = (psDroid->pos.x - player.p.x) - terrainMidX*TILE_UNITS;
	position.z = terrainMidY*TILE_UNITS - (psDroid->pos.y - player.p.z);
	position.y = psDroid->pos.z;

	if(psDroid->droidType == DROID_TRANSPORTER)
	{
		position.y += bobTransporterHeight();
	}

	/* Get all the pitch,roll,yaw info */
	rotation.y = -(SDWORD)psDroid->direction;
	rotation.x = psDroid->pitch;
	rotation.z = psDroid->roll;

	/* Translate origin */
	pie_TRANSLATE(position.x,position.y,position.z);

	/* Rotate for droid */
	pie_MatRotY(DEG(rotation.y));
	pie_MatRotX(DEG(rotation.x));
	pie_MatRotZ(DEG(rotation.z));

	if( (gameTime-psDroid->timeLastHit < GAME_TICKS_PER_SEC) && psDroid->lastHitWeapon == WSC_ELECTRONIC)
	{
		objectShimmy( (BASE_OBJECT*) psDroid );
	}

	if (psDroid->lastHitWeapon == WSC_EMP &&
	    (gameTime - psDroid->timeLastHit < EMP_DISABLE_TIME))
	{
		Vector3i position;

		//add an effect on the droid
		position.x = psDroid->pos.x + DROID_EMP_SPREAD;
		position.y = psDroid->pos.z + rand()%8;;
		position.z = psDroid->pos.y + DROID_EMP_SPREAD;
		effectGiveAuxVar(90+rand()%20);
		addEffect(&position,EFFECT_EXPLOSION,EXPLOSION_TYPE_PLASMA,false,NULL,0);
	}

	if (godMode || (psDroid->visible[selectedPlayer] == UBYTE_MAX) || demoGetStatus())
	{
		//ingame not button object
		//Watermelon:should render 3 mounted weapons now
		displayCompObj(psObj,false);
	}
	else
	{

		// make sure it's not over water.
		tileX = psDroid->pos.x/TILE_UNITS;
		tileY = psDroid->pos.y/TILE_UNITS;
		// double check it's on map
		if ( tileX < mapWidth && tileY < mapHeight )
		{
			psTile = mapTile(tileX,tileY);
			if (terrainType(psTile) != TER_WATER)
			{
			   	frame = gameTime/BLIP_ANIM_DURATION + psDroid->id; //visible[selectedPlayer];
			   	pie_Draw3DShape(getImdFromIndex(MI_BLIP), frame, 0, WZCOL_WHITE, WZCOL_BLACK, pie_ADDITIVE, psDroid->visible[selectedPlayer] / 2);
				/* set up all the screen coords stuff - need to REMOVE FROM THIS LOOP */
			}
		}
	}
	pie_MatEnd();
}


/* Assumes matrix context is already set */
// Watermelon:this is able to handle multiple weapon graphics now
// removed mountRotation,they get such stuff from psObj directly now
void displayCompObj(BASE_OBJECT *psObj, BOOL bButton)
{
	DROID				*psDroid;
	iIMDShape			*psShape, *psJet, *psShapeTemp = NULL;
	Vector3i				zero = {0, 0, 0};
	Vector2i				screenCoords;
	SDWORD				dummyZ, iConnector;
	PROPULSION_STATS	*psPropStats;
	SDWORD				frame;
	SDWORD				pieFlag, iPieData;
	PIELIGHT			brightness;
	const PIELIGHT			specular = WZCOL_BLACK;
	UDWORD				colour;
	UDWORD				bDarkSide = false;
	UBYTE	i;

   	/* Cast the droid pointer */
	psDroid = (DROID *)psObj;
	if( (gameTime-psDroid->timeLastHit < GAME_TICKS_PER_SEC/4 ) && psDroid->lastHitWeapon == WSC_ELECTRONIC && !gamePaused())
	{
		colour = getPlayerColour(rand()%MAX_PLAYERS);
		bDarkSide = true;
	}
	else
	{
		colour = getPlayerColour(psDroid->player);
	}

	//set pieflag for button object or ingame object
	if ( bButton )
	{
		pieFlag = pie_BUTTON;
	}
	else
	{
		pieFlag = 0;
	}

	if(!bButton)
	{
		brightness = pal_SetBrightness(psDroid->illumination);
		pieFlag = pie_SHADOW;
	}
	else
	{
		brightness = WZCOL_WHITE;
	}

	/* We've got a z value here _and_ screen coords of origin */
	dummyZ = pie_RotateProject(&zero, &screenCoords);

	/* set default components transparent */
	if ( psDroid->asBits[COMP_PROPULSION].nStat == 0 )
	{
		pieFlag  |= pie_TRANSLUCENT;
		iPieData  = DEFAULT_COMPONENT_TRANSLUCENCY;
	}
	else
	{
		iPieData = 0;
	}

	//Watermelon:uses psShapeTemp too separate it from turret's psShape
	psShapeTemp = (leftFirst ? getLeftPropulsionIMD(psDroid) : getRightPropulsionIMD(psDroid));
	if(psShapeTemp!=NULL)
	{
		pie_Draw3DShape(psShapeTemp, 0, colour, brightness, specular, pieFlag, iPieData);
	}

	/* set default components transparent */
	if ( psDroid->asBits[COMP_BODY].nStat == 0 )
	{
		pieFlag  |= pie_TRANSLUCENT;
		iPieData  = DEFAULT_COMPONENT_TRANSLUCENCY;
	}
	else
	{
		pieFlag  &= ~pie_TRANSLUCENT;
		iPieData = 0;
	}

	/* Get the body graphic now*/
	//Watermelon:uses psShapeTemp too separate it from turret's psShape
	psShapeTemp = BODY_IMD(psDroid,psDroid->player);
	if(psShapeTemp!=NULL)
	{
		// FIXME
		if ( psDroid->droidType == DROID_PERSON)
		{
			/* draw body if not animating */
			if ( psDroid->psCurAnim == NULL  || psDroid->psCurAnim->bVisible == false )
			{
				// FIXME - hideous....!!!!
				pie_MatScale(75);
				pie_Draw3DShape(psShapeTemp, 0, psDroid->player-6, brightness, specular, pieFlag, iPieData);
			}
		}
		//else if( psDroid->droidType == DROID_CYBORG)
	else if (cyborgDroid(psDroid))
		{
			/* draw body if cyborg not animating */
			if ( psDroid->psCurAnim == NULL || psDroid->psCurAnim->bVisible == false )
			{
				pie_Draw3DShape(psShapeTemp, 0, colour, brightness, specular, pieFlag, iPieData);
			}
		}
		else
		{
			pie_Draw3DShape(psShapeTemp, 0, colour, brightness, specular, pieFlag, iPieData);
		}
	}

	/* get propulsion stats */
	psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION].nStat;
	ASSERT( psPropStats != NULL,
			"moveUpdateUnit: invalid propulsion stats pointer" );

	/* render vtol jet if flying - horrible hack - GJ */
	if (((psPropStats->propulsionType == LIFT) &&
	    //(psDroid->droidType != DROID_CYBORG)) && (!bButton))
	    (!cyborgDroid(psDroid))) && (!bButton))
	{
		/* show flame if above ground */
		if ( psDroid->sMove.Status != MOVEINACTIVE )
 		{
			/* draw flame if found  */

			/* GJ TODO: add flame-finding code here */
			psJet = asBodyStats[psDroid->asBits[COMP_BODY].nStat].pFlameIMD;

			if ( psJet != NULL )
			{
				pie_Draw3DShape(psJet, getStaticTimeValueRange(100,psJet->numFrames), colour, brightness, specular, pie_ADDITIVE, 200);
			}
		}
	}

	//don't change the screen coords of an object if drawing it in a button
	if (!bButton)
	{
		/* set up all the screen coords stuff - need to REMOVE FROM THIS LOOP */
		calcScreenCoords(psDroid);
	}

	/* set default components transparent */
	if (psDroid->asWeaps[0].nStat              == 0 &&
	    psDroid->asBits[COMP_SENSOR].nStat     == 0 &&
	    psDroid->asBits[COMP_ECM].nStat        == 0 &&
	    psDroid->asBits[COMP_BRAIN].nStat      == 0 &&
	    psDroid->asBits[COMP_REPAIRUNIT].nStat == 0 &&
	    psDroid->asBits[COMP_CONSTRUCT].nStat  == 0)
	{
		pieFlag  |= pie_TRANSLUCENT;
		iPieData  = DEFAULT_COMPONENT_TRANSLUCENCY;
	}
	else
	{
		pieFlag  &= ~pie_TRANSLUCENT;
		iPieData = 0;
	}

	/* Indenting here is only to show new matrix context */
	{
		psShapeTemp = BODY_IMD(psDroid,psDroid->player);
		if( psShapeTemp->nconnectors )
		{
			/* vtol weapons attach to connector 2 (underneath);
			 * all others to connector 1 */
			/* Watermelon:VTOL's now skip the first 5 connectors(0 to 4),
			VTOL's use 5,6,7,8 etc now */
			if ( (psPropStats->propulsionType == LIFT) &&
				  psDroid->droidType == DROID_WEAPON )
			{
				iConnector = VTOL_CONNECTOR_START;
			}
			else
			{
				iConnector = 0;
			}

			switch(psDroid->droidType)
			{
			case DROID_DEFAULT:
			case DROID_TRANSPORTER:
			case DROID_CYBORG:
			case DROID_CYBORG_SUPER:
			case DROID_WEAPON:
			case DROID_COMMAND:		// command droids have a weapon to store all the graphics
				/*	Get the mounting graphic - we've already moved to the right position
				Allegedly - all droids will have a mount graphic so this shouldn't
				fall on it's arse......*/
				/* Double check that the weapon droid actually has any */
				//Watermelon:uses numWeaps
				//if(psDroid->numWeaps)
				for (i = 0;i < psDroid->numWeaps;i++)
				{
					if (psDroid->asWeaps[i].nStat > 0 || psDroid->droidType == DROID_DEFAULT)
					{
						if ( psShapeTemp->connectors )
						{
							pie_MatBegin();
							//Watermelon:reset Z?
							dummyZ = pie_RotateProject(&zero, &screenCoords);

							//Watermelon:to skip number of VTOL_CONNECTOR_START ground unit connectors
							if ( iConnector < VTOL_CONNECTOR_START )
							{
								pie_TRANSLATE(psShapeTemp->connectors[i].x,
								              psShapeTemp->connectors[i].z,
								              psShapeTemp->connectors[i].y);
							}
							else
							{
								pie_TRANSLATE( psShapeTemp->connectors[iConnector + i].x,
											   psShapeTemp->connectors[iConnector + i].z,
											   psShapeTemp->connectors[iConnector + i].y  );
							}

							if ( psDroid->turretRotation[i] )
							{
								pie_MatRotY(DEG( (-(SDWORD)psDroid->turretRotation[i])) );
							}


							/* vtol weapons inverted */
							if ( iConnector >= VTOL_CONNECTOR_START )
							{
								pie_MatRotZ( DEG_360/2 );//this might affect gun rotation
							}


							//psShape = WEAPON_MOUNT_IMD(psDroid,psDroid->player);
							psShape = (asWeaponStats[psDroid->asWeaps[i].nStat]).pMountGraphic;
							/* Draw it */
							//if(psDroid->numWeaps) already done this check above?!
							{
								pie_TRANSLATE(0,0,psDroid->asWeaps[i].recoilValue/3);
							}
							if(psShape)
							{
								pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData);
							}

							//if(psDroid->numWeaps) already done this check above?!
							{
								pie_TRANSLATE(0,0,psDroid->asWeaps[i].recoilValue);
							}

							/* translate for weapon mount point if cyborg */
							//if( psDroid->droidType == DROID_CYBORG &&
							if (cyborgDroid(psDroid) && psShape && psShape->nconnectors)
							{
								pie_TRANSLATE( psShape->connectors[0].x,
											   psShape->connectors[0].z,
											   psShape->connectors[0].y  );
							}

							/* vtol weapons inverted */
							if ( iConnector >= VTOL_CONNECTOR_START )
							{
								//pitch the barrel down
								pie_MatRotX(DEG( (-(psDroid->turretPitch[i])) ));
							}
							else
							{
								//pitch the barrel up
								pie_MatRotX(DEG(psDroid->turretPitch[i]));
							}

							/* Get the weapon (gun?) graphic */
							//psShape = WEAPON_IMD(psDroid,psDroid->player);
							psShape = (asWeaponStats[psDroid->asWeaps[i].nStat]).pIMD;
							/* Draw it */
							if(psShape)
							{
								pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData);
							}
							//we have a droid weapon so do we draw a muzzle flash
							if( psShape && psShape->nconnectors )
							{
								/* Now we need to move to the end fo the barrel */
								//Watermelon:fixed the bug,I mingled body connector and weapon connector :/
								pie_TRANSLATE( psShape->connectors[0].x,
											   psShape->connectors[0].z,
											   psShape->connectors[0].y  );
								//and draw the muzzle flash
								//animate for the duration of the flash only
								//Watermelon:change macro to actual accessor for each turret effect
								//psShape = MUZZLE_FLASH_PIE(psDroid,psDroid->player);
								psShape = (asWeaponStats[psDroid->asWeaps[i].nStat]).pMuzzleGraphic;
								if(psShape)
								{
									//assume no clan colours formuzzle effects
									if ((psShape->numFrames == 0) || (psShape->animInterval <= 0))//no anim so display one frame for a fixed time
									{
										if (gameTime < (psDroid->asWeaps[i].lastFired + BASE_MUZZLE_FLASH_DURATION))
										{
											pie_Draw3DShape(psShape, 0, 0, brightness, WZCOL_BLACK, pieFlag | pie_ADDITIVE, EFFECT_MUZZLE_ADDITIVE);//muzzle flash
										}
									}
									else
									{
										frame = (gameTime - psDroid->asWeaps[i].lastFired)/psShape->animInterval;
										if (frame < psShape->numFrames)
										{
											pie_Draw3DShape(psShape, frame, 0, brightness, WZCOL_BLACK, pieFlag | pie_ADDITIVE, EFFECT_MUZZLE_ADDITIVE);//muzzle flash
										}
									}
								}
							}
						}
						/* Pop Matrix */
						pie_MatEnd();
					}
				}
				break;

			case DROID_SENSOR:
				/*	Get the mounting graphic - we've already moved to the right position
				Allegedly - all droids will have a mount graphic so this shouldn't
				fall on it's arse......*/
				//Watermelon:sensor uses connectors[0]
				pie_MatBegin();
				//Watermelon:reset Z?
				dummyZ = pie_RotateProject(&zero, &screenCoords);
				/* vtol weapons inverted */
				if ( iConnector >= VTOL_CONNECTOR_START )
				{
					pie_MatRotZ( DEG_360/2 );//this might affect gun rotation
				}

				pie_TRANSLATE( psShapeTemp->connectors[0].x,
							   psShapeTemp->connectors[0].z,
							   psShapeTemp->connectors[0].y  );

				if(psDroid->turretRotation[0])
				{
					pie_MatRotY(DEG( (-(SDWORD)(psDroid->turretRotation[0])) ));
				}
				psShape = SENSOR_MOUNT_IMD(psDroid,psDroid->player);
				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0,colour, brightness, specular, pieFlag, iPieData);
				}

				/* Get the sensor graphic, assuming it's there */
				psShape = SENSOR_IMD(psDroid,psDroid->player);
				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0,colour, brightness, specular, pieFlag, iPieData);
				}
				/* Pop Matrix */
				pie_MatEnd();
				break;

			case DROID_CONSTRUCT:
			case DROID_CYBORG_CONSTRUCT:
				/*	Get the mounting graphic - we've already moved to the right position
				Allegedly - all droids will have a mount graphic so this shouldn't
				fall on it's arse......*/
				//Watermelon:cyborg uses connectors[0]
				pie_MatBegin();
				//Watermelon:reset Z?
				dummyZ = pie_RotateProject(&zero, &screenCoords);
				/* vtol weapons inverted */
				if ( iConnector >= VTOL_CONNECTOR_START )
				{
					pie_MatRotZ( DEG_360/2 );//this might affect gun rotation
				}
				pie_TRANSLATE( psShapeTemp->connectors[0].x,
							   psShapeTemp->connectors[0].z,
							   psShapeTemp->connectors[0].y  );

				if(psDroid->turretRotation[0])
				{
					pie_MatRotY(DEG( (-(SDWORD)(psDroid->turretRotation[0])) ));
				}
				psShape = CONSTRUCT_MOUNT_IMD(psDroid,psDroid->player);
				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0,colour, brightness, specular, pieFlag, iPieData);
				}

				/* translate for construct mount point if cyborg */
				if (cyborgDroid(psDroid) && psShape && psShape->nconnectors)
				{
					pie_TRANSLATE( psShape->connectors[0].x,
								   psShape->connectors[0].z,
								   psShape->connectors[0].y  );
				}

				/* Get the construct graphic assuming it's there */
				psShape = CONSTRUCT_IMD(psDroid,psDroid->player);

				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0,colour, brightness, specular, pieFlag, iPieData);
				}
				/* Pop Matrix */
				pie_MatEnd();
				break;
			case DROID_ECM:
				/*	Get the mounting graphic - we've already moved to the right position
				Allegedly - all droids will have a mount graphic so this shouldn't
				fall on it's arse......*/
				//Watermelon:ecm uses connectors[0]
				pie_MatBegin();
				//Watermelon:reset Z?
				dummyZ = pie_RotateProject(&zero, &screenCoords);
				/* vtol weapons inverted */
				if ( iConnector >= VTOL_CONNECTOR_START )
				{
					pie_MatRotZ( DEG_360/2 );//this might affect gun rotation
				}
				pie_TRANSLATE( psShapeTemp->connectors[0].x,
							   psShapeTemp->connectors[0].z,
							   psShapeTemp->connectors[0].y  );

				if(psDroid->turretRotation[0])
				{
					pie_MatRotY(DEG( (-(SDWORD)(psDroid->turretRotation[0])) ));
				}
				psShape = ECM_MOUNT_IMD(psDroid,psDroid->player);
				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData);
				}

				/* Get the ECM graphic assuming it's there.... */
				psShape = ECM_IMD(psDroid,psDroid->player);
				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData);
				}
				/* Pop Matrix */
				pie_MatEnd();
				break;
			case DROID_REPAIR:
			case DROID_CYBORG_REPAIR:
				/*	Get the mounting graphic - we've already moved to the right position
				Allegedly - all droids will have a mount graphic so this shouldn't
				fall on it's arse......*/
				//Watermelon:cyborg uses connectors[0]
				pie_MatBegin();
				//Watermelon:reset Z?
				dummyZ = pie_RotateProject(&zero, &screenCoords);
				/* vtol weapons inverted */
				if ( iConnector >= VTOL_CONNECTOR_START )
				{
					pie_MatRotZ( DEG_360/2 );//this might affect gun rotation
				}
				pie_TRANSLATE( psShapeTemp->connectors[0].x,
							   psShapeTemp->connectors[0].z,
							   psShapeTemp->connectors[0].y  );

				if(psDroid->turretRotation[0])
				{
					pie_MatRotY(DEG( (-(SDWORD)(psDroid->turretRotation[0])) ));
				}
				psShape = REPAIR_MOUNT_IMD(psDroid,psDroid->player);
				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData);
				}

				/* translate for construct mount point if cyborg */
				if (cyborgDroid(psDroid) && psShape && psShape->nconnectors)
				{
					pie_TRANSLATE( psShape->connectors[0].x,
								   psShape->connectors[0].z,
								   psShape->connectors[0].y  );
				}

				/* Get the Repair graphic assuming it's there.... */
				psShape = REPAIR_IMD(psDroid,psDroid->player);

				/* Draw it */
				if(psShape)
				{
					pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData);
					if(psShape->nconnectors && psDroid->action == DACTION_DROIDREPAIR)
					{
						pie_TRANSLATE( psShape->connectors[0].x,
									   psShape->connectors[0].z,
									   psShape->connectors[0].y  );
						pie_TRANSLATE(0,-20,0);

						psShape = getImdFromIndex(MI_FLAME);

						/* Rotate for droid */
						pie_MatRotY( DEG( (SDWORD)psDroid->direction ) );
						pie_MatRotX( DEG( -psDroid->pitch ) );
						pie_MatRotZ( DEG( -psDroid->roll ) );
						//Watermelon:rotate Y
					   	pie_MatRotY(DEG( -( (-(SDWORD)(psDroid->turretRotation[0])) ) ));

						iV_MatrixRotateY(-player.r.y);
						iV_MatrixRotateX(-player.r.x);
							/* Dither on software */

					   	pie_Draw3DShape(psShape, getStaticTimeValueRange(100,psShape->numFrames), 0, brightness, WZCOL_BLACK, pie_ADDITIVE, 140);
					  		/* Dither off software */

						iV_MatrixRotateX(player.r.x);
						iV_MatrixRotateY(player.r.y);
					}
				}
				/* Pop Matrix */
				pie_MatEnd();
					break;
			case DROID_PERSON:
				// no extra mounts for people
				break;
			default:
				ASSERT(!"invalid droid type", "Whoa! Weirdy type of droid found in drawComponentObject!!!");
				break;
			}
		}
		/*	We've also got a handle on the psShape here for the weapon which has a connector to point to
			muzzle flash attachment points - just grab it from psShape->connectors->[x|y|z] */
	} // end of illustrative indentation - see above

	/* set default components transparent */
	if ( psDroid->asBits[COMP_PROPULSION].nStat == 0 )
	{
		pieFlag  |= pie_TRANSLUCENT;
		iPieData  = DEFAULT_COMPONENT_TRANSLUCENCY;
	}
	else
	{
		pieFlag  &= ~pie_TRANSLUCENT;
		iPieData = 0;
	}

	psShape = (leftFirst ? getRightPropulsionIMD(psDroid) : getLeftPropulsionIMD(psDroid));
	if(psShape!=NULL)
	{
		pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData);
	}
}


void destroyFXDroid(DROID	*psDroid)
{
	UDWORD	i;
	iIMDShape	*psImd = NULL;
	SDWORD	widthScatter, breadthScatter, heightScatter;
	Vector3i pos;

 	widthScatter = TILE_UNITS/4;
	breadthScatter = TILE_UNITS/4;
	heightScatter = TILE_UNITS/5;
	for(i=0; i<5; i++)
	{
		pos.x = psDroid->pos.x + widthScatter - rand()%(2*widthScatter);
		pos.z = psDroid->pos.y + breadthScatter - rand()%(2*breadthScatter);
		pos.y = psDroid->pos.z + 16 +heightScatter;
		switch(i)
		{
		case 0:
			switch(psDroid->droidType)
			{
			case DROID_DEFAULT:
			case DROID_CYBORG:
			case DROID_CYBORG_SUPER:
			case DROID_CYBORG_CONSTRUCT:
			case DROID_CYBORG_REPAIR:
			case DROID_WEAPON:
			case DROID_COMMAND:
				if (psDroid->numWeaps > 0)
				{
					if(psDroid->asWeaps[0].nStat > 0)
					{
						psImd = WEAPON_MOUNT_IMD(psDroid,psDroid->player);
					}
				}
				else
				{
					psImd = getRandomDebrisImd();
				}
				break;
			default:
				psImd = getRandomDebrisImd();
				break;
			}
			break;
		case 1:
			switch(psDroid->droidType)
			{
			case DROID_DEFAULT:
			case DROID_CYBORG:
			case DROID_CYBORG_SUPER:
			case DROID_CYBORG_CONSTRUCT:
			case DROID_CYBORG_REPAIR:
			case DROID_WEAPON:
			case DROID_COMMAND:
				if(psDroid->numWeaps)
				{
					psImd = WEAPON_IMD(psDroid,psDroid->player);
				}
				else
				{
					psImd = getRandomDebrisImd();
				}
				break;
			default:
				psImd = getRandomDebrisImd();
				break;
			}
			break;
		case 2:
		case 3:
		case 4:
			psImd = getRandomDebrisImd();
			break;
		}
		if(psImd)
		{
			addEffect(&pos,EFFECT_GRAVITON,GRAVITON_TYPE_EMITTING_DR,true,psImd,getPlayerColour(psDroid->player));
		}
		else
		{
			addEffect(&pos,EFFECT_GRAVITON,GRAVITON_TYPE_EMITTING_DR,true,getRandomDebrisImd(),0);
		}
	}
}


void	compPersonToBits(DROID *psDroid)
{
	Vector3i position;	//,rotation,velocity;
	iIMDShape	*headImd, *legsImd, *armImd, *bodyImd;
	UDWORD		groundHeight;
	UDWORD		col;

	if(!psDroid->visible[selectedPlayer])
	{
		/* We can't see the person or cyborg - so get out */
		return;
	}
	/* get bits pointers according to whether baba or cyborg*/
	if (cyborgDroid(psDroid))
	{
		headImd = getImdFromIndex(MI_CYBORG_HEAD);
		legsImd = getImdFromIndex(MI_CYBORG_LEGS);
		armImd  = getImdFromIndex(MI_CYBORG_ARM);
		bodyImd = getImdFromIndex(MI_CYBORG_BODY);
	}
	else
	{
		headImd = getImdFromIndex(MI_BABA_HEAD);
		legsImd = getImdFromIndex(MI_BABA_LEGS);
		armImd  = getImdFromIndex(MI_BABA_ARM);
		bodyImd = getImdFromIndex(MI_BABA_BODY);
	}

	/* Get where he's at */
	position.x = psDroid->pos.x;
	position.y = psDroid->pos.z+1;
	groundHeight = psDroid->pos.z;
	position.z = psDroid->pos.y;


	/* Tell about player colour */
	col = getPlayerColour(psDroid->player);

	addEffect(&position,EFFECT_GRAVITON,GRAVITON_TYPE_GIBLET,true,headImd,col);
	addEffect(&position,EFFECT_GRAVITON,GRAVITON_TYPE_GIBLET,true,legsImd,col);
	addEffect(&position,EFFECT_GRAVITON,GRAVITON_TYPE_GIBLET,true,armImd,col);
	addEffect(&position,EFFECT_GRAVITON,GRAVITON_TYPE_GIBLET,true,bodyImd,col);
}


iIMDShape *getLeftPropulsionIMD(DROID *psDroid)
{
	UDWORD			bodyStat, propStat;
	iIMDShape		**imd;

	bodyStat = psDroid->asBits[COMP_BODY].nStat;
	propStat = psDroid->asBits[COMP_PROPULSION].nStat;

	imd = asBodyStats[bodyStat].ppIMDList;
	imd += (propStat * NUM_PROP_SIDES + LEFT_PROP);

	return *imd;
}


iIMDShape *getRightPropulsionIMD(DROID *psDroid)
{
	UDWORD			bodyStat, propStat;
	iIMDShape		**imd;

	bodyStat = psDroid->asBits[COMP_BODY].nStat;
	propStat = psDroid->asBits[COMP_PROPULSION].nStat;

	imd = asBodyStats[bodyStat].ppIMDList;
	imd += (propStat * NUM_PROP_SIDES + RIGHT_PROP);

	return *imd;
}


SDWORD	rescaleButtonObject(SDWORD radius, SDWORD baseScale,SDWORD baseRadius)
{
	SDWORD newScale;
	newScale = 100 * baseRadius;
	newScale /= radius;
	if(baseScale > 0)
	{
		newScale += baseScale;
		newScale /= 2;
	}
	return newScale;
}
